<?php

namespace StudyBuddy\Controllers;

use \StudyBuddy\Utf8String;
use \StudyBuddy\WebPage;
use \StudyBuddy\Request;
use \StudyBuddy\Responder;
use \StudyBuddy\CommentParser;
use \StudyBuddy\SubmittedCommentWWW;


/**
 * Controller is responsible for
 * parsing user generated comment
 * to question or answer
 *
 * @todo add support for replyid
 * comment may have replyid in which
 * case it will be a reply to existing comment
 * in case of reply an commentor (user) should
 * be notified when someone replied to their comment
 *
 */
class Addcomment extends WebPage
{
	protected $membersOnly = true;

	protected $aRequired = array('rid', 'com_body');

	protected $requireToken = true;

	protected $bRequirePost = true;

	/**
	 * Resource for which this comment
	 * is being processed
	 * this will be either \StudyBuddy\Answer
	 * or \StudyBuddy\Question
	 * object
	 *
	 * @var object of type StudyBuddy\Answer
	 * or \StudyBuddy\Question but will implement StudyBuddy\StudyBuddyObject
	 */
	protected $oResource;


	protected $oCommentParser;

	protected function main(){
		$this->oRegistry->registerObservers('INPUT_FILTERS');

		$this->getResource()
		->checkPermission()
		->add()
		->returnResult();
	}



	/**
	 * Use Comments class to add
	 * comment to COMMENTS collection
	 * and to push to the actual resource
	 *
	 * @return object $this
	 */
	protected function add(){

		$this->oCommentParser = new CommentParser($this->oRegistry);
		$this->oCommentParser->add(new SubmittedCommentWWW($this->oRegistry, $this->oResource));

		return $this;
	}
	

	/**
	 * Create object of type Question or Answer
	 *
	 * @return object $this
	 */
	protected function getResource(){

		$a = $this->oRegistry->Mongo->RESOURCE->findOne(array('_id' => $this->oRequest['rid']));
		d('a: '.print_r($a, 1));
		$collection = 'QUESTIONS';
		if(empty($a)){
			throw new \StudyBuddy\Exception('RESOURCE NOT FOUND by id '.$this->oRequest['rid']);
		}

		if(!empty($a['res_type']) && ('ANSWER' === $a['res_type'] )){
			$collection = 'ANSWERS';
		}
		
		$rid = (int)$this->oRequest['rid'];
		d('$collection: '.$collection. ' $rid: '.$rid);

		$coll = $this->oRegistry->Mongo->getCollection($collection);
		$a = $coll->findOne(array('_id' => $rid));
		d('a: '.print_r($a, 1));

		if(empty($a)){

			throw new \StudyBuddy\Exception('Item not found');
		}

		$class = ('QUESTIONS' === $collection) ? '\\StudyBuddy\\Question' : '\\StudyBuddy\\Answer';

		$this->oResource = new $class($this->oRegistry, $a);

		return $this;
	}


	/**
	 * Who can comment?
	 * Usually it's owner of resource
	 * OR owner of question for which this resource is
	 * an answer
	 * OR someone with enough reputation
	 *
	 *
	 * @return object $this
	 *
	 */
	protected function checkPermission(){
		$viewerID = $this->oRegistry->Viewer->getUid();

		/**
		 * If NOT question owner AND NOT Resource owner
		 * AND Reputation below required 
		 * THEN must have 'comment' permission
		 * 
		 * This means in order to comment Viewer
		 * must be owner of Question OR owner of Answer
		 * OR have enough reputation
		 * OR have special 'comment' permission
		 */
		if(
		($this->oResource->getQuestionOwnerId() !== $viewerID) &&
		($this->oResource->getOwnerId() !== $viewerID) &&
		($this->oRegistry->Viewer->getReputation() < \StudyBuddy\Points::COMMENT)){
			try{
				$this->checkAccessPermission('comment');
			} catch(\Exception $e){
				
				/**
				 * If this is an AuthException then it means
				 * user does not have 'comment' permission in the ACL
				 * which also means that user does not have
				 * the required reputation score.
				 * We will show a nice message then.
				 *
				 * In case it's some other type of exception just re-throw it
				 */
				if($e instanceof \StudyBuddy\AccessException){
					
					throw new \StudyBuddy\Exception('A minimum reputation score of '.\StudyBuddy\Points::COMMENT.
					' is required to comment on someone else\'s question or answer. 
					Your current reputation score is '.$this->oRegistry->Viewer->getReputation());
				}else {
					throw $e;
				}
			}
		}

		return $this;
	}


	/**
	 * Return array of resourceID, type (A or Q)
	 * and parsed div with comment
	 *
	 *
	 */
	protected function returnResult(){
		$aComment = $this->oCommentParser->getArrayCopy();
		
		/**
		 * Add edit and delete tools because
		 * Viewer already owns this comment and is
		 * allowed to edit or delete it right away.
		 * Javascript that usually dynamically adds these tools
		 * is not going to be fired, so these tools
		 * must alreayd be included in the returned html
		 *
		 */
		$aComment['edit_delete'] = '  <span class="ico del ajax" title="Delete">delete</span> <span class="ico edit ajax" title="Edit">edit</span>';
		
		/**
		 * Important to add owner_id key
		 * because it's not in the comment array
		 * It is used when creating the 'reply' link
		 * in the tplComment
		 * That ID is then used when figuring out if
		 * viewer has permission to add comment.
		 * Users with low reputation still always have
		 * premission to add comments to own resources.
		 * 
		 */
		$aComment['owner_id'] = $this->oResource->getOwnerId();
		
		$aRet = array(
			'comment' => array('id' => $aComment['_id'],
			'res' =>  $aComment['i_res'],
			'parent' => $aComment['i_prnt'],
			'html' => \tplComment::parse($aComment))
		);

		Responder::sendJSON($aRet);

	}
}
